home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / boi120p.zip / UNITS.ZIP / IOLIB.PAS < prev    next >
Pascal/Delphi Source File  |  1990-12-12  |  16KB  |  548 lines

  1. {$D-}
  2. {$S-}
  3. {$V-}
  4.  
  5. Unit IOLib;
  6. { Part of BBS Onliner Interface }
  7. { Copyright (C) 1990 Andrew J. Mead
  8.   All Rights Reserved. }
  9.  
  10. { BBS Onliner Interface contains
  11.   Async     - low-level serial port communications interrupt handler
  12.   BOIDecl   - BOI standard declarations
  13.   IOLib     - standard console and port communications routines
  14.   IOSupp    - extended character code processing for IOLib-ReadPortKey
  15.   GetCmBBS  - command line parser
  16.   Support   - common library functions and procedures }
  17.  
  18. { Original version 7/1/90
  19.   Original release version 1.0 beta 9/5/90
  20.   Version  1.01  9/19/90 /Q quiet local mode switch added
  21.   Version  1.01b 9/20/90 realname usage added, /A Remote Access defined
  22.   Version  1.02  9/22/90 RA access removed, /Q switch fixed
  23.   Version  1.03  9/23/90 /A play it Again switch added
  24.   Version  1.10  9/24/90 /2, /F, /M, /H, /5, /6 switches added
  25.   Version  1.11  9/29/90 beta version of /B locked baud rate
  26.   Version  1.12 10/ 1/90 /P switch added
  27.   Version  1.13 10/10/90 /N switch added
  28.   Version  1.14 10/22/90 /B switch fixed, carrier dectect routines added
  29.   Version  1.15 10/25/90 internal reorginizations, /K added
  30.   Version  1.16 11/ 9/90 /K fixed, F-9 abort added.
  31.   Version  1.17 12/ 1/90 internal reorginizations.
  32.   Version  1.17b12/ 5/90 /P fixed, /O implemented
  33.   Version  1.18 12/ 9/90 /O,/P verified /1,/3 implemented.
  34.   Version  1.20 12/10/90 Initial Public Release.
  35.  
  36. }
  37.  
  38. INTERFACE
  39.  
  40. Uses
  41.   Dos;
  42.  
  43. { Standard Functions }
  44.  
  45.   Function MIN(a,b : word) : word;
  46.   Function MAX(a,b : word) : word;
  47.  
  48.   {* Internal timing *}
  49.   Procedure TIMERSET(var basetime : longint); { initialize timer value }
  50.   Function GETTIMER(  {boolean}             { true if val seconds has passed }
  51.       var basetime : longint;               { starting time }
  52.       val          : word)                  { number of seconds }
  53.       : boolean;
  54.  
  55.   {* file validation *}
  56.   Function EXIST(thisfile : pathstr) : boolean;
  57.   Function VALID(thisfile : pathstr) : boolean;
  58.  
  59. { Memory Function }
  60.   Function KEYPRESSED : Boolean;   { RAM - check keyboard buffer }
  61.  
  62. { BIOS Functions }
  63.   Function READKEY : char;         { BIOS - get key from keyboard buffer }
  64.   Function WHEREX : byte;          { BIOS - get current cursor x position }
  65.   Function WHEREY : byte;          { BIOS - get current cursor y position }
  66.   Procedure DELAY(ms : Word);      { BIOS - CPU delay, 993 = 1 second }
  67.  
  68. { ANSI Functions }
  69.   { Input/Output string procedures }
  70.   Procedure SENDSTRING(            { send string to output }
  71.       outstr : string;             { string to output }
  72.       docr : boolean);             { send CR/LF indicator }
  73.   Function INTSTR( { returns a string of the input integer }
  74.       val : longint;               { value to convert }
  75.       isize : byte) : string;      { padded size of the string }
  76.   Function REALSTR({ returns a string of the input real value }
  77.       rval  : real;                { value to convert }
  78.       rsize,                       { padded size of the string }
  79.       rdec  : byte) : string;      { number of decimal places in string }
  80.   Function PADSTR( { returns a right justified string }
  81.       pstr : string;               { string to right justify }
  82.       psize : byte) : string;      { size of string }
  83.   Procedure GETSTRING(var gstr : string);  { all input chars upto next CR }
  84.  
  85.   { Housecleaning procedures }
  86.   Procedure SETPORT;               { Initialize Async Communications }
  87.   Procedure ENDPORT;               { Terminate Async Communications }
  88.  
  89.   { Positional/Attribute Functions }
  90.   Procedure GOTOPORTXY(x,y : byte);  { Position cursor at given coordinates }
  91.   Procedure PORTCOLOR(  { if docolor then set acolor else set bcolor }
  92.       acolor,                      { color text attributes }
  93.       bcolor : byte);              { monochrome text attributes }
  94.   Procedure TEXTPORTCOLOR(color : byte);  { set text attributes }
  95.   Procedure PORTBACKGROUND(color: byte);  { set background attributes }
  96.   Procedure CLRPORTSCR;            { clear current window }
  97.   Procedure CLRPORTEOL;            { clear current line to End Of Line }
  98.   Procedure PORTWINDOW(x1,y1,x2,y2 : byte);  { Set display Window }
  99.   Procedure PORTCOLUMNONE;         { put cursor in column one on current line }
  100.  
  101.   { Basic Input function }
  102.   Function READPORTKEY : char;     { get input character }
  103.   Function PORTKEYPRESSED : boolean; { character ready for processing }
  104.  
  105.   { reset function }
  106.   Procedure CLEARBUFFERS;          { clear keyboard and port input buffers }
  107.  
  108.   { Advanced positional group }
  109.   Procedure SETPORTXY;             { save current cursor position }
  110.   Procedure RESETPORTXY;           { restore saved cursor position }
  111.  
  112.   { Timeout procedure }
  113.   Function LEFTTIME : integer;     { remaing player time in minutes }
  114.   Procedure DOTIMEOUT(ringbell : boolean); { exit program due to inactivity }
  115.  
  116. IMPLEMENTATION
  117.  
  118. Uses
  119.   boidecl,
  120.   iosupp,
  121.   Async;
  122.  
  123. Const
  124.   null  = #0;
  125.   bell  = #7;
  126.   esc   = #27;
  127.   f10   = #$44; {scan code}
  128.   basex : byte = 1;
  129.   basey : byte = 1;
  130.   tempx : byte = 1;
  131.   tempy : byte = 1;
  132.   endx  : byte = 24;
  133.   endy  : byte = 80;
  134.  
  135. Var
  136.   regs        : registers;
  137.   textattr    : word;
  138.   workstr     : string;
  139.  
  140. Function MIN(a,b : word) : word;
  141.   begin {* fMin *}
  142.     if a < b then Min := a else Min := b
  143.   end;  {* fMin *}
  144.  
  145. Function MAX(a,b : word) : word;
  146.   begin {* fMax *}
  147.     if a > b then Max := a else Max := b
  148.   end;  {* fMax *}
  149.  
  150. Procedure TIMERSET(var basetime : longint);
  151.   begin {* TimerSet *}
  152.     move(memw[$40:$6C],basetime,4)
  153.   end;  {* TimerSet *}
  154.  
  155. Function GETTIMER(var basetime : longint; val : word) : boolean;
  156.   var thistime : longint;
  157.  
  158.   begin {* GetTimer *}
  159.     move(memw[$40:$6C],thistime,4);
  160.     GetTimer := trunc((thistime - basetime) / 18.2) > val;
  161.   end;  {* GetTimer *}
  162.  
  163. Function EXIST(thisfile : pathstr) : boolean;
  164.   var
  165.     afile : file;
  166.     iocode : word;
  167.  
  168.   begin {* fExist *}
  169.     assign(afile,thisfile);
  170.     {$I-}
  171.     reset(afile);
  172.     {$I+}
  173.     iocode := ioresult;
  174.     Exist := (iocode = 0);
  175.     if iocode = 0 then close(afile);
  176.   end;  {* fExist *}
  177.  
  178. Function VALID(thisfile : pathstr) : boolean;
  179.   Var
  180.     afile : file;
  181.     check : boolean;
  182.     iocode : word;
  183.  
  184.   begin {* fValid *}
  185.     if not Exist(thisfile) then
  186.       begin
  187.         assign(afile,thisfile);
  188.         {$I-}
  189.         rewrite(afile);
  190.         close(afile);
  191.         erase(afile);
  192.         {$I+}
  193.         iocode := ioresult;
  194.         Valid := (iocode = 0)
  195.       end
  196.     else Valid := true
  197.   end;  {* fValid *}
  198.  
  199.  
  200. Procedure DELAY(MS: Word);
  201.   begin {* Delay *}
  202.     with regs do
  203.       begin
  204.         ah := $86;
  205.         move(ms,cx,2);
  206.         Intr($15,regs)
  207.       end
  208.   end;  {* Delay *}
  209.  
  210. Function KEYPRESSED : Boolean;
  211.   begin {* KeyPressed *}
  212.     Keypressed := MemW[$0040:$001C] <> MemW[$0040:$001A]
  213.   end;  {* KeyPressed *}
  214.  
  215.  
  216. Function READKEY : char;
  217.   var key : char;
  218.  
  219.   begin {* fReadKey *}
  220.     setfunction := false;
  221.     with regs do
  222.       begin
  223.         repeat                   { wait until keypressed }
  224.           begin
  225.             ah := $01;           { check to see if keyboard buffer is empty }
  226.             Intr($16,regs)
  227.           end
  228.         until flags and fzero = 0;
  229.         ah := $00;               { get next keycode from keyboard buffer }
  230.         Intr($16,regs);
  231.         move(al,key,1);
  232.         if key = null then       { if local keyboard has pressed a function }
  233.           begin                  { key, replace the #0 value with the scan  }
  234.             setfunction := true; { code of the key pressed. }
  235.             move(ah,key,1)
  236.           end;
  237.         ReadKey := key
  238.       end
  239.   end;  {* fReadKey *}
  240.  
  241. Function WHEREX : byte;
  242.   begin {* fWhereX *}
  243.     with regs do
  244.       begin
  245.         ah := $03;
  246.         bh := $00;
  247.         Intr($10,regs);
  248.         WhereX := dl + 2 - baseX
  249.       end
  250.   end;  {* fWhereX *}
  251.  
  252. Function WHEREY : byte;
  253.   begin {* fWhereY *}
  254.     with regs do
  255.       begin
  256.         ah := $03;
  257.         bh := $00;
  258.         Intr($10,regs);
  259.         WhereY := dh + 2 - baseY
  260.       end
  261.   end;  {* fWhereY *}
  262.  
  263.  
  264. Procedure SENDSTRING(outstr : string;docr : boolean);
  265.   var
  266.     sloop : byte;
  267.  
  268.   begin {* SendString *}
  269.     if not dolocal then
  270.       begin
  271.         for sloop := 1 to length(outstr) do SendChar(outstr[sloop]);
  272.         if docr then
  273.           begin
  274.             SendChar(char($0D));       { send CR }
  275.             SendChar(char($0A))        { send LF }
  276.           end
  277.       end;
  278.     if dolocal or doecho then
  279.       begin
  280.         if doquiet then for sloop := length(outstr) downto 1 do if outstr[sloop] = bell then delete(outstr,sloop,1);
  281.         write(outstr);
  282.         if docr then writeln
  283.       end
  284.   end;  {* SendString *}
  285.  
  286. Function INTSTR(val : longint;isize : byte) : string;
  287.   var
  288.     ist : string;
  289.  
  290.   begin {* fIntStr *}
  291.     Str(val:isize,ist);
  292.     IntStr := ist
  293.   end;  {* fIntStr *}
  294.  
  295. Function REALSTR(rval : real; rsize,rdec : byte) : string;
  296.   var
  297.     ist : string;
  298.  
  299.   begin {* fRealStr *}
  300.     Str(rval:rsize:rdec,ist);
  301.     RealStr := ist
  302.   end;  {* fRealStr *}
  303.  
  304. Function PADSTR(pstr : string; psize : byte) : string;
  305.   var
  306.     tstr : string;
  307.  
  308.   begin {* fPadStr *}
  309.     if length(pstr) > psize then PadStr := pstr
  310.     else
  311.       begin
  312.         fillchar(tstr[1],psize,32);
  313.         tstr[0] := chr(psize);
  314.         move(pstr[1],tstr[psize - length(pstr) + 1],length(pstr));
  315.         PadStr := tstr
  316.       end
  317.   end;  {* fPadStr *}
  318.  
  319. Function READPORTKEY : char;
  320.   var
  321.     rkey     : char;
  322.     timebase : longint;
  323.  
  324.   begin {* fReadPortKey *}
  325.     if dolocal then
  326.       begin
  327.         rkey := ReadKey;
  328.         if setfunction then CheckSecondKey(rkey)
  329.       end
  330.     else
  331.       begin
  332.         TimerSet(timebase);
  333.         repeat until CharReady or KeyPressed or GetTimer(timebase,60) or not Carrier;
  334.         if not (KeyPressed or CharReady) and Carrier and GetTimer(timebase,60) then
  335.           begin
  336.             SendString(bell,false);
  337.             repeat until charready or keypressed or GetTimer(timebase,120) or not Carrier
  338.           end;
  339.         if not Carrier then DoTimeOut(false)
  340.         else if not (KeyPressed or CharReady) and GetTimer(timebase,120) then DoTimeOut(true)
  341.         else if CharReady then rkey := ReadBuffer
  342.         else if KeyPressed then
  343.           begin
  344.             rkey := ReadKey;
  345.             if setfunction then CheckSecondKey(rkey)
  346.           end
  347.       end;
  348.     ReadPortKey := rkey
  349.   end;  {* fReadPortKey *}
  350.  
  351. Function PORTKEYPRESSED : boolean;
  352.   begin {* fPortKeyPressed *}
  353.     if dolocal then PortKeyPressed := KeyPressed
  354.     else PortKeyPressed := KeyPressed or CharReady
  355.   end;  {* fPortKeyPressed *}
  356.  
  357. Procedure CLEARBUFFERS;
  358.   var cbchar : char;
  359.  
  360.   begin {* ClearBuffers *}
  361.     while keypressed do cbchar := ReadKey;
  362.     if not dolocal then ClearInBuffer
  363.   end;  {* ClearBuffers *}
  364.  
  365. Procedure GETSTRING(var gstr : string);
  366.   var
  367.     gchar : char;
  368.  
  369.   begin {* GetString *}
  370.     if dolocal then readln(gstr)
  371.     else
  372.       begin
  373.         gstr := '';
  374.         repeat
  375.           begin
  376.             gchar := ReadPortKey;
  377.             if gchar in [#32..#126] then
  378.               begin
  379.                 gstr := gstr + gchar;
  380.                 SendString(gchar,false)
  381.               end
  382.             else if (gchar = #8) and (length(gstr) > 0) then
  383.               begin
  384.                 delete(gstr,length(gstr),1);
  385.                 SendString(gchar,false)
  386.               end
  387.           end
  388.         until gchar = #13;
  389.         SendString('',true)
  390.       end
  391.   end;  {* GetString *}
  392.  
  393. Procedure SETPORT;
  394.   begin {* SetPort *}
  395.     if not dolocal then IntInit
  396.   end;  {* SetPort *}
  397.  
  398. Procedure ENDPORT;
  399.   begin {* EndPort *}
  400.     if not dolocal then IntEnd
  401.   end;  {* EndPort *}
  402.  
  403. Procedure GOTOPORTXY(x,y : byte);
  404.   begin {* GotoPortXY *}
  405.     x := x + basex - 1;
  406.     y := y + basey - 1;
  407.     SendString(esc+'['+IntStr(y,0)+';'+IntStr(x,0)+'H',false)
  408.   end;  {* GotoPortXY *}
  409.  
  410. Procedure SETCOLOR(color : byte);
  411.   begin {* SetColor *}
  412.     if color > 150 then {* Blink + High Intensity *}
  413.       begin
  414.         SendString(esc+'[01;05;'+IntStr(color-150,0)+'m',false);
  415.         textattr := 0
  416.       end
  417.     else if color > 100 then {* Blink + Low Intensity *}
  418.       begin
  419.         SendString(esc+'[00;05;'+IntStr(color-100,0)+'m',false);
  420.         textattr := 0
  421.       end
  422.     else if color > 50 then {* High Intesity *}
  423.       begin
  424.         SendString(esc+'[00;01;'+IntStr(color-50,0)+'m',false);
  425.         textattr := 0
  426.       end
  427.     else {* Low Intesity *}
  428.       begin
  429.         SendString(esc+'[00;'+IntStr(color,0)+'m',false);
  430.         textattr := 0
  431.       end
  432.   end;  {* SetColor *}
  433.  
  434. Procedure PORTCOLOR(acolor, bcolor : byte);
  435.   begin {* PortColor *}
  436.     if docolor then SetColor(acolor) else SetColor(bcolor)
  437.   end;  {* PortColor *}
  438.  
  439. Procedure TEXTPORTCOLOR(color : byte);
  440.   begin {* TextPortColor *}
  441.     SetColor(color)
  442.   end;  {* TextPortColor *}
  443.  
  444. Procedure PORTBACKGROUND(color: byte);
  445.   begin {* PortBackground *}
  446.     if color in [30..37] then SendString(esc+'[00;'+IntStr(color+10,0)+'m',false)
  447.   end;  {* PortBackground *}
  448.  
  449. Procedure CLRPORTSCR;
  450.   var
  451.     cloop : byte;
  452.  
  453.   Procedure GOTOSTATUSLINE;
  454.     begin {* ClrPortScr,GotoStatusLine *}
  455.       with regs do
  456.         begin
  457.           ah := $02;       { use BIOS gotoxy function }
  458.           bh := $00;       { use current video screen }
  459.           dh := 24;        { goto line 24 (0-24) }
  460.           dl := 0;         { goto column 0 (0-79) }
  461.           Intr($10,regs)
  462.         end
  463.     end;  {* ClrPortScr,GotoStatusLine *}
  464.  
  465.   begin {* ClrPortScr *}
  466.     if basey = 1 then
  467.       begin
  468.         SendString(esc+'[2J',false);
  469.         if usename and not dolocal then
  470.           begin
  471.             SetPortXY;
  472.             GotoStatusLine;
  473.             workstr := 'Current Player : ' + username;
  474.             if usereal then workstr := workstr + ', ' + realname;
  475.             if length(workstr) > 79 then workstr[0] := chr(79);
  476.             write(workstr);
  477.             ResetPortXY
  478.           end
  479.       end
  480.     else for cloop := endy - basey + 1 downto 1 do
  481.       begin
  482.         GotoPortXY(1,cloop);
  483.         if cloop < 24 then SendString(esc+'[K',false)
  484.         else SendString('                                                                             ',false)
  485.       end
  486.   end;  {* ClrPortScr *}
  487.  
  488. Procedure CLRPORTEOL;
  489.   begin {* ClrPortEOL *}
  490.     SendString(esc+'[K',false)
  491.   end;  {* ClrPortEOL *}
  492.  
  493. Procedure PORTWINDOW(x1,y1,x2,y2 : byte);
  494.   begin {* PortWindow *}
  495.     basex := x1;
  496.     basey := y1;
  497.     endx := Min(80,x2);
  498.     endy := Min(24,y2);
  499.     GotoPortXY(1,1);
  500.   end;  {* PortWindow *}
  501.  
  502. Procedure PORTCOLUMNONE;
  503.   begin {* PortColumnOne *}
  504.     SendString(esc+'[79D',false)
  505.   end;  {* PortColumnOne *}
  506.  
  507. Procedure SETPORTXY;
  508.   begin {* SetPortXY *}
  509.     SendString(esc+'[s',false);
  510.     if doecho then
  511.       begin
  512.         TempX := WhereX;
  513.         TempY := WhereY
  514.       end
  515.   end;  {* SetPortXY *}
  516.  
  517. Procedure RESETPORTXY;
  518.   Procedure GOTOXY(x,y : byte);
  519.     begin {* GotoXY *}
  520.       x := x + basex - 1;
  521.       y := y + basey - 1;
  522.       write(esc,'[',y:0,';',x:0,'H')
  523.     end;  {* GotoXY *}
  524.  
  525.   begin {* ResetPortXY *}
  526.     SendString(esc+'[u',false);
  527.     if doecho then gotoxy(TempX,TempY)
  528.   end;  {* ResetPortXY *}
  529.  
  530. Procedure DOTIMEOUT(ringbell : boolean);
  531.   begin {* DoTimeOut *}
  532.     if ringbell then SendString(bell,true);
  533.     write(esc,'[2J');
  534.     write('Program timeout.  ');
  535.     if Carrier then writeln('No input for 2 minutes.') else writeln('Carrier Dropped.');
  536.     writeln('Returning control to BBS.');
  537.     EndPort;
  538.     halt
  539.   end;  {* DoTimeOut *}
  540.  
  541. Function LEFTTIME : integer;
  542.   begin {* fLeftTime *}
  543.     GetTime(thishour,thismin,second,hunsec);
  544.     if (hour = 23) and (thishour = 0) then thishour := 24;
  545.     LeftTime := timeleft + minute-thismin - 60*(thishour-hour)
  546.   end;  {* fLeftTime *}
  547.  
  548. end. Unit